﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ChoWorkflowServer.Model;
using System.Threading.Tasks;
using System.Threading;
using Cinchoo.Core.Diagnostics;
using Cinchoo.Core.Services;
using Cinchoo.Core.ETL;
using Cinchoo.Core;

namespace ChoWorkflowServer
{
    internal class ChoDependencyWorkflowScheduler
    {
        private readonly object _padLock = new object();
        private readonly Dictionary<string, ChoTasksDataSet.CHO_TASK_SCHEDULESRow> _jobDetails = new Dictionary<string, ChoTasksDataSet.CHO_TASK_SCHEDULESRow>();
        private readonly IChoDataModel _dataModel = ChoDataModelFactory.New();
        private readonly ChoDelayFireDependencyTaskScheduler _delayFireDependencyTaskScheduler = new ChoDelayFireDependencyTaskScheduler();

        public ChoDependencyWorkflowScheduler()
        {
        }

        public void FireDependentTasks(int batchId, string taskName, string scheduleName, string user, string originHostName)
        {
            ChoTasksDataSet.CHO_DEPENDENCY_TASKSDataTable depedencies = _dataModel.GetAllDepedencyTasks(ChoJobNameHelper.ToJobName(taskName, scheduleName));
            foreach (ChoTasksDataSet.CHO_DEPENDENCY_TASKSRow dependencyRow in depedencies)
            {
                try
                {
                    if (!CanTrigger(dependencyRow))
                        continue;

                    //int batchId = ChoRandom.NextRandom();
                    //if (!ChoWorkflowServerEx.Instance.FireActivateTask(batchId, dependencyRow.TASK_NAME, dependencyRow.SCHEDULE_NAME, true, user, originHostName))
                    //    continue;
                    ChoWorkflowServerEx.Instance.FireActivateTask(batchId, dependencyRow.TASK_NAME, dependencyRow.SCHEDULE_NAME, true, user, originHostName);

                    if (dependencyRow.FIRE_AFTER_DEPENDENCY < 0)
                    {
                    }
                    else if (dependencyRow.FIRE_AFTER_DEPENDENCY == 0)
                    {
                        ChoWorkflowServerEx.Instance.FireStartTask(batchId, dependencyRow.TASK_NAME, dependencyRow.SCHEDULE_NAME, dependencyRow.WORKFLOW_NAME, user, originHostName);
                    }
                    else
                    {
                        _delayFireDependencyTaskScheduler.ScheduleTask(batchId, dependencyRow.TASK_NAME, dependencyRow.SCHEDULE_NAME, dependencyRow.WORKFLOW_NAME, dependencyRow.FIRE_AFTER_DEPENDENCY);
                    }
                }
                catch (Exception innerEx)
                {
                    ChoTrace.Write(innerEx);
                }
            }
        }

        public void CancelDependentTask(string taskName, string scheduleName)
        {
            _delayFireDependencyTaskScheduler.CancelTask(taskName, scheduleName);
        }

        public void FireActivateDependentTasks(int batchId, string taskName, string scheduleName, string user, string originHostName)
        {
            ChoTasksDataSet.CHO_DEPENDENCY_TASKSDataTable depedencies = _dataModel.GetAllDepedencyTasks(ChoJobNameHelper.ToJobName(taskName, scheduleName));
            foreach (ChoTasksDataSet.CHO_DEPENDENCY_TASKSRow dependencyRow in depedencies)
            {
                try
                {
                    if (dependencyRow.IsDEPENDENCIESNull()
                        || dependencyRow.DEPENDENCIES.IsNullOrWhiteSpace())
                        continue;

                    if (dependencyRow.IsTASK_STATUSNull() 
                        //|| (ChoETLWorkflowStatus)dependencyRow.TASK_STATUS == ChoETLWorkflowStatus.ACTIVE
                        || (ChoETLWorkflowStatus)dependencyRow.TASK_STATUS == ChoETLWorkflowStatus.RUNNING
                        || (ChoETLWorkflowStatus)dependencyRow.TASK_STATUS == ChoETLWorkflowStatus.INACTIVE
                        )
                        continue;


                    //int batchId = ChoRandom.NextRandom();
                    if (!ChoWorkflowServerEx.Instance.FireActivateTask(batchId, dependencyRow.TASK_NAME, dependencyRow.SCHEDULE_NAME, true, user, originHostName))
                        continue;
                }
                catch (Exception innerEx)
                {
                    ChoTrace.Write(innerEx);
                }
            }
        }

        private bool CanTrigger(ChoTasksDataSet.CHO_DEPENDENCY_TASKSRow dependencyRow)
        {
            if (dependencyRow.IsDEPENDENCIESNull()
                || dependencyRow.DEPENDENCIES.IsNullOrWhiteSpace())
                return false;

            if (dependencyRow.IsTASK_STATUSNull() || (ChoETLWorkflowStatus)dependencyRow.TASK_STATUS == ChoETLWorkflowStatus.INACTIVE)
                return false;

            using (ChoLexParser lex = new ChoLexParser(dependencyRow.DEPENDENCIES))
            {
                try
                {
                    return lex.Evaluate();
                }
                catch (Exception ex)
                {
                    ChoTrace.Write(ex);
                    return false;
                }
            }
        }
    }
}
